Skip to content

Conversation

@alan-j-hu
Copy link
Contributor

  • CMAKE_{STATIC,SHARED}_LIBRARY_SUFFIX reports incorrect suffixes for Mac. Use .so and .a for both Mac and Linux.
  • Add LLVM_OCAML_EXTERNAL_LLVM_LIBDIR option.
  • LLVM dynamic library is always suffixed with major version

- CMAKE_{STATIC,SHARED}_LIBRARY_SUFFIX reports incorrect suffixes for Mac.
  Use .so and .a for both Mac and Linux.
- Add LLVM_OCAML_EXTERNAL_LLVM_LIBDIR option.
- LLVM dynamic library is always suffixed with major version
@alan-j-hu alan-j-hu requested a review from Ericson2314 January 18, 2025 21:31
@llvmbot llvmbot added the cmake Build system in general and CMake in particular label Jan 18, 2025
@alan-j-hu alan-j-hu requested a review from nikic January 18, 2025 21:31
@nikic
Copy link
Contributor

nikic commented Jan 18, 2025

CMAKE_{STATIC,SHARED}_LIBRARY_SUFFIX reports incorrect suffixes for Mac. Use .so and .a for both Mac and Linux.

What's the incorrect suffix that gets reported? Your change doesn't really make sense to me, as the dylib suffix for MacOs is .dylib, not .so.

@alan-j-hu
Copy link
Contributor Author

@nikic

See https://github.com/ocaml/opam-source-archives/blob/main/patches/llvm/fix-macos.patch.14.0.6, for example. This patch is necessary to distribute the LLVM OCaml bindings on opam.

In the given CMake snippet, we are working in OCaml land, not C/C++ land. The OCaml compiler generates .so and .a for its outputs, including on Mac.

@alan-j-hu
Copy link
Contributor Author

Fixed up more of the logic.

In the CMake code of concern, we are talking about the outputs of ocamlmklib. This should output .o and .a files on Mac, which should render the usage of CMake variables incorrect. See https://ocaml.org/manual/5.3/intfc.html#s%3Aocamlmklib.

set(ocaml_inputs)

set(ocaml_outputs "${bin}/${name}.cma")
# Always use -custom when building in-tree
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we always use -custom for in-tree builds? Based on https://ocaml.org/manual/4.10/intfc.html#ss:staticlink-c-code, do I correctly understand that you need -custom if you're linking statically? Wasn't the previous BUILD_SHARED_LIBS based condition correct for that?

@alan-j-hu
Copy link
Contributor Author

Thank you for the review. The CMake code on the main branch is

  if( NOT BUILD_SHARED_LIBS )
    list(APPEND ocaml_flags "-custom")
  endif()

I did some investigation and figured out that if you leave out the -custom flag, when you run the test suite, you will hit errors that look like

: CommandLine Error: Option 'experimental-debuginfo-iterators' registered more than once!
LLVM ERROR: inconsistency in registered CommandLine options

and the tests will fail.

This seems to be an issue with CommandLine, talked about at https://discourse.llvm.org/t/rfc-commandline-allow-loading-1-library-linking-to-the-same-libllvm-version/67542. If BUILD_SHARED_LIBS=ON, then this error will occur. Passing the -custom flag when building the OCaml bindings forces static linking, avoiding this issue.

However, it seems that when building out-of-tree and installing the bindings as an OCaml package, the -custom flag causes bytecode executables not to work. I get errors that look like:

/usr/bin/ld: cannot find -lllvm_analysis: No such file or directory
/usr/bin/ld: cannot find -lllvm_executionengine: No such file or directory
/usr/bin/ld: cannot find -lctypes_stubs: No such file or directory
/usr/bin/ld: cannot find -lintegers_stubs: No such file or directory
/usr/bin/ld: cannot find -lllvm_target: No such file or directory
/usr/bin/ld: cannot find -lllvm: No such file or directory
collect2: error: ld returned 1 exit status

(I tried testing this with LLVM 14, which is the last version published on OPAM to build with CMake, but the bytecode executable failed to build for a different reason that has since been fixed: https://discuss.ocaml.org/t/llvm-symbol-not-found-for-bytecode-compilation/8728.)

So, it seems that when building in-tree, -custom is necessary for building bytecode executables, but when building out-of-tree and installing, -custom causes the bytecode executable to fail. (The -custom flag only affects bytecode executables generated by ocamlc, not native executables generated by ocamlopt.)

@alan-j-hu
Copy link
Contributor Author

I uncovered an issue when running OCaml bytecode executables, compiled using the LLVM static library. It's difficult for me to test this PR because of the way OCaml packages are handled. Therefore, I am currently not confident in my ability to ensure this PR is correct. I need to take a breather and figure out a good way to test the OCaml package installation (perhaps via CI), before continuing to work on this.

Comment on lines +58 to +61
"${bin}/lib${name}.a")
if ( NOT ocaml_custom )
list(APPEND ocaml_outputs
"${bin}/dll${name}${CMAKE_SHARED_LIBRARY_SUFFIX}")
"${bin}/dll${name}.so")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you change the suffixes? What about Windows when we have .lib and .dll?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see past talk on this, I still don't like this solution, however.

Copy link
Member

@Ericson2314 Ericson2314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO the solution is to move the the bindings outside of /llvm and instead imitate how the other "packages" works. (See MLIR_STANDALONE_BUILD, CLANG_STANDALONE_BUILD, OPENMP_STANDALONE_BUILD etc.)

$ cmake -DLLVM_OCAML_OUT_OF_TREE=TRUE \
-DCMAKE_INSTALL_PREFIX=[Preinstalled LLVM path] \
-DLLVM_OCAML_INSTALL_PATH=[OCaml install prefix] \
-DLLVM_OCAML_EXTERNAL_LLVM_LIBDIR=[LLVM libdir, e.g. `llvm-config --libdir`] \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't do this, instead with an OCAML_BINDINGS_BUILD_STANDALONE we would do a findPackage(LLVM ...). That in turn would set LLVM_LIBRARY_DIR to be the external dir, and we wouldn't need the conditions below.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cmake Build system in general and CMake in particular

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants